/*
 * Copyright (c) 2010, Leon Dang f3it.com
 *           (c) 2010, Andrew Korolev redfox14 at gmail dot com
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *   * Neither the name of the Leon Dang & FCUBEDIT nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <QSqlQuery>
#include <QSqlRecord>
#include <QMessageBox>
#include <QString>
#include <QObject>
#include <QVariant>

#include "logdb.h"
#include "dbrecord.h"
#include "settings.h"

LogDB::LogDB( QObject * parent ): QObject( parent )
{
}

LogDB::~LogDB()
{
}

bool LogDB::connectDB()
{
	bool result = true;
	m_db = QSqlDatabase::addDatabase( "QSQLITE" );
	m_db.setDatabaseName( DB_LOC );
	if ( ! m_db.open() )
	{
		QMessageBox::critical(0, QString("Cannot open database"),
			QString("Unable to establish database connection"),
			QMessageBox::Cancel);
		result = false;
	}
	
	return result;
}

void LogDB::disconnectDB()
{
	if ( m_dbq != NULL )
	{
		m_dbq->finish();
		delete m_dbq;
		m_dbq = NULL;
	}
	m_db.close();
	QSqlDatabase::removeDatabase( "QSQLITE" );
}

bool LogDB::setupQuery( OptionsClass::FilterOptions filterOptions, int maxRecords )
{
	bool result = true;
	m_dbq = new QSqlQuery( m_db );
	m_dbq->setForwardOnly( true );

	QString eventFilter;

	if ( filterOptions.testFlag( OptionsClass::ShowMissed ) &&
		 filterOptions.testFlag( OptionsClass::ShowCalls ) )
	{
		eventFilter.append( "event_type_id = 3" );
	}
	else if ( filterOptions.testFlag( OptionsClass::ShowCalls ) )
	{
		eventFilter.append( "( event_type_id = 1 or event_type_id = 3" );
		if ( filterOptions.testFlag( OptionsClass::ShowSMS ) )
			eventFilter.append( " or event_type_id = 7" );
		eventFilter.append( " )");
	}
	else if ( filterOptions.testFlag( OptionsClass::ShowSMS ) )
	{
		eventFilter.append( "event_type_id = 7" );
	}

	if ( filterOptions.testFlag( OptionsClass::ShowIncoming ) )
	{
		if ( eventFilter.length() > 0)
			eventFilter.append( " and " );
		eventFilter.append( "outgoing = 0" );
	}
	else if ( filterOptions.testFlag( OptionsClass::ShowOutgoing ) )
	{
		if ( eventFilter.length() > 0)
			eventFilter.append( " and " );
		eventFilter.append( "outgoing = 1" );
	}

	if ( eventFilter.length() > 0)
	{
		if ( eventFilter.startsWith('(') && eventFilter.endsWith(')') )
		{
			eventFilter.prepend( "and ");
		}
		else
		{
			eventFilter.prepend( "and (" );
			eventFilter.append( ")" );
		}
	}

	// Updated to the el-v1.db design of PR1.2
	QString s = QString( "select event_type_id, start_time, end_time, is_read, E.local_uid, E.remote_uid, free_text, "
		"outgoing, remote_name from Events E, Remotes R where R.remote_uid=E.remote_uid and "
		"E.local_uid=R.local_uid %1 order by start_time desc limit %2" ).arg( eventFilter ) .arg( maxRecords );

	if ( ! m_dbq->exec( s ) )
	{
		QMessageBox::critical( 0, QString( "SQL EXEC Error" ), QString( "EXEC query failed" ), QMessageBox::Cancel );
		disconnectDB();
		result = false;
	}

	return result;
}

DBRecord * LogDB::getNextRecord() const
{
	DBRecord * rec = 0;
	
	if ( m_dbq->next() )
	{
		int type = m_dbq->value( 0 ).value< int >();
		if ( type == ELDB_CALL || type == ELDB_MISSED_CALL )
		{
			CallRecord * callRec = new CallRecord();
			callRec->setRecordType( ET_CALL );
			
			callRec->setStartTime( m_dbq->value( 1 ).value< uint >() );
			callRec->setEndTime( m_dbq->value( 2 ).value< uint >() );
			
			QString str = m_dbq->value( 4 ).value< QString >();
			if ( str == "ring/tel/ring" )
				callRec->setCallType( CT_CELL );
			else if ( str.contains( "spirit/skype" ) )
				callRec->setCallType( CT_SKYPE );
/*!!! To-Do: fing out the correct identification string !!!			
			else if ()
				callRec->setCallType( CT_GOOGLE ); */
	
			str = m_dbq->value( 5 ).value< QString >();
			callRec->setPhoneNumber( str );
			
			if ( type == ELDB_CALL )
				callRec->setDirection( m_dbq->value( 7 ).value< bool >() ? ED_OUTGOING: ED_INCOMING );
			else
				callRec->setDirection( ED_MISSED );
			
			str = m_dbq->value( 8 ).value< QString >();
			callRec->setName( str );
			
			rec = callRec;
		}
		else if	( type == ELDB_VOICEMAIL )
		{
			// This should never be for now.
		}
		else if ( type == ELDB_CHAT )
		{
			// This should never be for now.
		}
		else if ( type == ELDB_SMS )
		{
			SMSRecord * SMSRec = new SMSRecord();
			SMSRec->setRecordType( ET_SMS );

			SMSRec->setStartTime( m_dbq->value( 1 ).value< uint >() );
			SMSRec->setEndTime( m_dbq->value( 2 ).value< uint >() );
			SMSRec->setRead( m_dbq->value( 3 ).value< bool >() );
			QString str = m_dbq->value( 5 ).value< QString >();
			SMSRec->setPhoneNumber( str );
			str = m_dbq->value( 6 ).value< QString >();
			SMSRec->setText( str );
			SMSRec->setDirection( m_dbq->value( 7 ).value< bool >() ? ED_OUTGOING: ED_INCOMING );
			str = m_dbq->value( 8 ).value< QString >();
			SMSRec->setName( str );

			rec = SMSRec;
		}
	}
	return rec;
}
